package view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.text.DecimalFormat;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.NumberFormatter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import model.Player;
import model.Playlist;
import model.PlaylistRecord;
import model.Preference;
import model.Settings;
import net.miginfocom.swing.MigLayout;
import platform.PlatformObjectFactory;
import util.IView;
import util.LoggingUtils;
import util.PlayerUtilities;

public class AdminFrame extends JFrame implements IView, WindowListener, TreeSelectionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Preference preference;
	private Player player;
	private static AdminFrame _instance;
	private JCheckBox chckbxShowTransitions;
	private JCheckBox chckbxResendContentOn;
	private JCheckBox chckbxSendPlaylistrecordId;
	private JCheckBox chckbxEnableDebugMessage;
	private JCheckBox chckbxNoPauseTime;
	private JCheckBox chckbxUploadLogs;
	private JCheckBox chckbxClearContentOnStartUp;
	private JCheckBox chckbxCheckUpdates;
	private JCheckBox chckbxEnableLog;
	private JCheckBox chckbxEmailSending;

	private JFormattedTextField fmtbxUpdateFrequency;
	private JFormattedTextField fmtbxPlayerHeight;
	private JFormattedTextField fmtbxPlayerWidth;
	private JFormattedTextField fmtbxMemorySize;

	private JFormattedTextField fmtbxSCTime;
	private JComboBox cmbSCday;

	private JSlider sliderPlayerScale;
	private JFormattedTextField fmtbxBoxID;
	private JCheckBox chckbxFtpFileTransfer;
	private JFrame parentFrame;
	private JLabel lblVersionNumber;
	private JTree resourceTree;
	private JSplitPane playlistManagerPane;

	public static boolean isrestart = false;

	public static AdminFrame getInstance() {
		if (_instance == null) {
			_instance = new AdminFrame();
		}
		return _instance;
	}

	private AdminFrame() {
		this.player = Player.getInstance();
		this.preference = Preference.getInstance();
		this.preference.addView(this);
		this.player.addView(this);
		this.addWindowListener(this);

		this.setResizable(false);

		JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP);
		this.getContentPane().add(tabbedPane, BorderLayout.CENTER);

		JPanel panel = new JPanel();
		tabbedPane.addTab("Preferences", null, panel, null);
		panel.setLayout(new MigLayout("", "[][][][grow]", "[][][][][][][][][][][][][][][][][][][][][]"));

		JLabel lblPlayerVersion = new JLabel("Player Version:");
		panel.add(lblPlayerVersion, "cell 0 0,alignx trailing");

		this.lblVersionNumber = new JLabel(Double.toString(Settings.VERSION)+" beta");
		panel.add(this.lblVersionNumber, "cell 1 0");

		JLabel lblBoxId = new JLabel("Box ID:");
		panel.add(lblBoxId, "cell 0 1,alignx trailing");

		this.fmtbxBoxID = new JFormattedTextField(new NumberFormatter(new DecimalFormat("#0")));
		this.fmtbxBoxID.setColumns(10);
		panel.add(this.fmtbxBoxID, "cell 1 1,growx");

		JLabel lblScale = new JLabel("Scale:");
		panel.add(lblScale, "cell 0 2,alignx trailing");

		this.sliderPlayerScale = new JSlider();
		this.sliderPlayerScale.setMinimum(10);
		panel.add(this.sliderPlayerScale, "cell 1 2 3 1,growx");

		JLabel lblPlayerWidth = new JLabel("Player Width:");
		panel.add(lblPlayerWidth, "cell 0 3,alignx trailing");

		this.fmtbxPlayerWidth = new JFormattedTextField(new NumberFormatter(new DecimalFormat("#0")));
		panel.add(this.fmtbxPlayerWidth, "cell 1 3,growx");

		JLabel lblPlayerHeight = new JLabel("Player Height:");
		panel.add(lblPlayerHeight, "cell 0 4,alignx trailing");

		this.fmtbxPlayerHeight = new JFormattedTextField(new NumberFormatter(new DecimalFormat("#0")));
		panel.add(this.fmtbxPlayerHeight, "cell 1 4,growx");

		JLabel lblUpdateFrequency = new JLabel("Update Frequency:");
		panel.add(lblUpdateFrequency, "cell 0 5,alignx trailing");

		this.fmtbxUpdateFrequency = new JFormattedTextField(new NumberFormatter(new DecimalFormat("#0")));
		panel.add(this.fmtbxUpdateFrequency, "cell 1 5,growx");

		JLabel lblMemoerySize	= new JLabel("Memory Size:");
		panel.add(lblMemoerySize,"cell 0 6,alignx trailing");

		this.fmtbxMemorySize = new JFormattedTextField(new NumberFormatter(new DecimalFormat("#0")));
		panel.add(this.fmtbxMemorySize, "cell 1 6,growx");

		JLabel lblMemoerySizeUnit	= new JLabel("MB");
		panel.add(lblMemoerySizeUnit,"cell 1 6");


		JLabel lblSchedule	= new JLabel("Restart player at:");
		panel.add(lblSchedule,"cell 0 7,alignx trailing");

		this.fmtbxSCTime = new JFormattedTextField();
		panel.add(this.fmtbxSCTime, "cell 1 7");

		this.cmbSCday = new JComboBox();
		this.cmbSCday.addItem("Never");
		this.cmbSCday.addItem("Once a day");
		this.cmbSCday.addItem("Once a week");
		this.cmbSCday.addItem("Once a month");
		//this.cmbSCday.addI
		panel.add(this.cmbSCday,"cell 1 7");


		this.chckbxEnableDebugMessage = new JCheckBox("Enable Debug Message");
		this.chckbxEnableDebugMessage.setEnabled(false);
		panel.add(this.chckbxEnableDebugMessage, "cell 1 8");

		this.chckbxNoPauseTime = new JCheckBox("No Pause Time");
		panel.add(this.chckbxNoPauseTime, "cell 2 8");

		this.chckbxSendPlaylistrecordId = new JCheckBox("Send PlaylistRecord ID");
		this.chckbxSendPlaylistrecordId.setEnabled(false);
		panel.add(this.chckbxSendPlaylistrecordId, "cell 1 9");

		this.chckbxUploadLogs = new JCheckBox("Upload Logs");
		this.chckbxUploadLogs.setEnabled(false);
		panel.add(this.chckbxUploadLogs, "cell 2 9");

		this.chckbxResendContentOn = new JCheckBox("Resend Content On Startup");
		panel.add(this.chckbxResendContentOn, "cell 1 10");

		this.chckbxClearContentOnStartUp = new JCheckBox("Clear Content On Startup");
		this.chckbxClearContentOnStartUp.setEnabled(false);
		panel.add(this.chckbxClearContentOnStartUp, "cell 2 10");

		this.chckbxShowTransitions = new JCheckBox("Show Transitions");
		this.chckbxShowTransitions.setEnabled(false);
		panel.add(this.chckbxShowTransitions, "cell 1 11");

		this.chckbxCheckUpdates = new JCheckBox("Check Updates");
		panel.add(this.chckbxCheckUpdates, "cell 2 11");

		this.chckbxEnableLog = new JCheckBox("Enable Log");
		panel.add(this.chckbxEnableLog, "cell 2 12");


		this.chckbxFtpFileTransfer = new JCheckBox("FTP File Transfer");
		this.chckbxFtpFileTransfer.setEnabled(false);
		panel.add(this.chckbxFtpFileTransfer, "cell 1 12");

		this.chckbxEmailSending = new JCheckBox("Send email");
		panel.add(this.chckbxEmailSending, "cell 1 13");

		JButton btnCancel = new JButton("Cancel");
		btnCancel.addActionListener(new CancelChangesActionListener());

		JButton btnSavePreferences = new JButton("Save Preferences");
		btnSavePreferences.addActionListener(new SaveChangesActionListener());
		panel.add(btnSavePreferences, "cell 1 17,alignx right");
		panel.add(btnCancel, "cell 2 17");

		playlistManagerPane = new JSplitPane();
		tabbedPane.addTab("Playlist Manager", null, playlistManagerPane, null);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setPreferredSize(new Dimension(150, 2));
		playlistManagerPane.setLeftComponent(scrollPane);
		playlistManagerPane.setRightComponent(new JButton("awfd"));

		DefaultMutableTreeNode top = getRootTreeNode();
		this.resourceTree = new JTree(top);
		this.resourceTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		this.resourceTree.addTreeSelectionListener(this);
		scrollPane.setViewportView(resourceTree);

		JPanel panel_2 = new JPanel();
		this.getContentPane().add(panel_2, BorderLayout.SOUTH);

		JButton btnResetPlayer = new JButton("Clear Player");
		btnResetPlayer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Thread resetPlayerThread = new Thread(new Runnable() {

					@Override
					public void run() {
						LoggingUtils.logStart("Class AdminFrame.java, reset player button");
						LoggingUtils.log(Level.SEVERE, "User cleared the player in AdminFrame.java");

						PlayerUtilities.recursiveDelete(Settings.XML_DIRECTORY);
						PlayerUtilities.recursiveDelete(Settings.VIDEO_DIRECTORY);
						PlayerUtilities.recursiveDelete(Settings.IMAGE_DIRECTORY);
						PlayerUtilities.recursiveDelete(Settings.HTML_DIRECTORY);
						PlayerUtilities.createDirectories();

						PlatformObjectFactory.getInstance().getCommandExecutor().resetPlayer();

					}
				});
				resetPlayerThread.start();
			}
		});

		// Test Button
		JButton btnTest = new JButton("Test Update");
		btnTest.setEnabled(false);
		btnTest.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Thread updateThread = new Thread(new Runnable() {

					@Override
					public void run() {
						Player player = Player.getInstance();
						player.update();
						player.downloadContents();
					}
				});
				updateThread.setName("test update thread");
				updateThread.start();
			}
		});
		panel_2.add(btnTest);

		panel_2.add(btnResetPlayer);

		JButton btnNewButton = new JButton("Resend Content");
		btnNewButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Thread resendContentThread = new Thread(new Runnable() {
					@Override
					public void run() {
						net.HttpRequestFacade.resendContent();
					}
				});
				resendContentThread.start();
			}
		});

		panel_2.add(btnNewButton);

		JButton btnRestartPlayer = new JButton("Restart Player");
		btnRestartPlayer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				LoggingUtils.logStart("Class AdminFrame.java, restart player button");
				LoggingUtils.log(Level.SEVERE, "User restarting the player in AdminFrame.java");

				// Mailing the error 
				//String EmailBody = EmailSending.ProcessEmailBody("User restarted the player in AdminFrame.java", "Player is restarted by user, player restarting ", "Player is restarted forcefully by user from admin panel");
				//System.out.println(EmailBody);			
				//util.EmailSending.getInstance().send(Settings.TO_USER, "Restarting:AdminFrame:" +
				//		"BoxID="+Preference.getInstance().getBoxID(), EmailBody);

				PlatformObjectFactory.getInstance().getCommandExecutor().restartPlayer();
			}
		});

		panel_2.add(btnRestartPlayer);

		JButton btnQuitPlayer = new JButton("Quit Player");
		btnQuitPlayer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				PlatformObjectFactory.getInstance().getCommandExecutor().quitPlayer();
			}
		});

		panel_2.add(btnQuitPlayer);

		JButton btnClose = new JButton("Close");
		btnClose.addActionListener(new CloseWindowActionListener());
		panel_2.add(btnClose);
		this.updateUI();
	}

	private DefaultMutableTreeNode getRootTreeNode() {
		DefaultMutableTreeNode top = new DefaultMutableTreeNode("Playlists");
		for (Playlist playlist : Player.getInstance().getPlaylists()) {
			DefaultMutableTreeNode playlistNode = new DefaultMutableTreeNode(playlist.getName());
			for (PlaylistRecord rec : playlist.getRecords()) {
				DefaultMutableTreeNode recordNode = new DefaultMutableTreeNode(rec);
				playlistNode.add(recordNode);
			}
			top.add(playlistNode);

		}
		return top;
	}

	@Override
	public void updateView(Object obj, Object additionalInformation) {
		// TODO Auto-generated method stub
		this.updateUI();
	}

	public void updateUI() {
		this.fmtbxBoxID.setText(Integer.toString(Preference.getInstance().getBoxID()));
		this.sliderPlayerScale.setValue((int) (Preference.getInstance().getScale() * 100));
		this.fmtbxPlayerWidth.setText(Integer.toString(Preference.getInstance().getPlayerWidth()));
		this.fmtbxPlayerHeight.setText(Integer.toString(Preference.getInstance().getPlayerHeight()));
		this.fmtbxUpdateFrequency.setText(Integer.toString(Preference.getInstance().getUpdateCheckerFrequency()));
		this.fmtbxMemorySize.setText(Integer.toString(Preference.getInstance().getMemorySize()));

		if(Preference.getInstance().getScheduleTime().equals(""))
		{
			this.fmtbxSCTime.setText("03:00:00");
		}
		else
		{
			this.fmtbxSCTime.setText(Preference.getInstance().getScheduleTime());
		}
		this.cmbSCday.setSelectedIndex(Preference.getInstance().getScheduleday());


		this.chckbxCheckUpdates.setSelected(Preference.getInstance().isCheckUpdates());
		this.chckbxEnableLog.setSelected(Preference.getInstance().isCheckLogging());
		this.chckbxEmailSending.setSelected(Preference.getInstance().isEheckEmailSending());
		this.chckbxClearContentOnStartUp.setSelected(Preference.getInstance().isClearContentOnStartup());
		this.chckbxEnableDebugMessage.setSelected(Preference.getInstance().isDebugEnabled());
		this.chckbxFtpFileTransfer.setSelected(Preference.getInstance().isFtpTransfer());
		this.chckbxResendContentOn.setSelected(Preference.getInstance().isResendContentOnStartup());
		this.chckbxSendPlaylistrecordId.setSelected(Preference.getInstance().isSendPlaylistRecord());
		this.chckbxShowTransitions.setSelected(Preference.getInstance().isTransitionEnabled());
		this.chckbxUploadLogs.setSelected(Preference.getInstance().isUploadLogs());
		this.chckbxNoPauseTime.setSelected(Preference.getInstance().isZeroPauseTime());
		this.resourceTree = new JTree(this.getRootTreeNode());
		this.resourceTree.addTreeSelectionListener(this);
		this.playlistManagerPane.setLeftComponent(this.resourceTree);
		this.playlistManagerPane.setRightComponent(new JPanel());
		this.playlistManagerPane.setDividerLocation(200);
		this.validate();
		this.repaint();
	}

	public void  saveChanges() {
		try
		{
			boolean viewupdate = false;
			
			if (this.fmtbxBoxID.getText().length() != 0) {
				Preference.getInstance().setBoxID(Integer.parseInt(this.fmtbxBoxID.getText()));
			}

			if (this.fmtbxPlayerHeight.getText().length() != 0) {
				if(Preference.getInstance().getPlayerHeight() !=Integer.parseInt(this.fmtbxPlayerHeight.getText()))
				{
					viewupdate = true;
				}
				Preference.getInstance().setPlayerHeight(Integer.parseInt(this.fmtbxPlayerHeight.getText()));
			}

			if (this.fmtbxPlayerWidth.getText().length() != 0) {
				
				if(Preference.getInstance().getPlayerWidth() !=Integer.parseInt(this.fmtbxPlayerWidth.getText()))
				{
					viewupdate = true;
				}
				Preference.getInstance().setPlayerWidth(Integer.parseInt(this.fmtbxPlayerWidth.getText()));
			}

			if (this.fmtbxUpdateFrequency.getText().length() != 0) {
				Preference.getInstance().setUpdateCheckerFrequency(Integer.parseInt(this.fmtbxUpdateFrequency.getText()));
			}

			System.out.println(Preference.getInstance().getMemorySize()+ " Difference "+this.fmtbxMemorySize.getText());

			if (this.fmtbxMemorySize.getText().length() != 0) {
				Preference.getInstance().setMemorySize(Integer.parseInt(this.fmtbxMemorySize.getText()));
			}

			if(Preference.getInstance().getScale() != ((double) (this.sliderPlayerScale.getValue()) / 100))
			{
				viewupdate = true;
			}
			
			Preference.getInstance().setScale((double) (this.sliderPlayerScale.getValue()) / 100);
			
			Preference.getInstance().setCheckUpdates(this.chckbxCheckUpdates.isSelected());
			Preference.getInstance().setCheckLogging(this.chckbxEnableLog.isSelected());
			Preference.getInstance().setEheckEmailSending(this.chckbxEmailSending.isSelected());
			Preference.getInstance().setClearContentOnStartup(this.chckbxClearContentOnStartUp.isSelected());
			Preference.getInstance().setDebugEnabled(this.chckbxEnableDebugMessage.isSelected());
			Preference.getInstance().setFtpTransfer(this.chckbxFtpFileTransfer.isSelected());
			Preference.getInstance().setResendContentOnStartup(this.chckbxResendContentOn.isSelected());
			Preference.getInstance().setSendPlaylistRecord(this.chckbxSendPlaylistrecordId.isSelected());
			Preference.getInstance().setTransitionEnabled(this.chckbxShowTransitions.isSelected());
			Preference.getInstance().setUploadLogs(this.chckbxUploadLogs.isSelected());
			Preference.getInstance().setZeroPauseTime(this.chckbxNoPauseTime.isSelected());

			Preference.getInstance().setScheduleTime(getSchedulteTime(this.fmtbxSCTime.getText()));


			if(Preference.getInstance().getScheduleday() != this.cmbSCday.getSelectedIndex())
			{
				Settings.isRestart = true;
			}

			Preference.getInstance().setScheduleday(this.cmbSCday.getSelectedIndex());

			Preference.getInstance().save();

			if(Settings.isRestart)
			{
				Settings.isRestart = false;
				System.out.println("Memory size change and schedule restart need player to restart");
				PlatformObjectFactory.getInstance().getCommandExecutor().restartPlayer();
			}
			
			if(viewupdate)
			{
				Preference.getInstance().notifyViews();
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private class CancelChangesActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			AdminFrame.this.updateUI();

		}

	}

	private String getSchedulteTime(String time)
	{
		String TIME24HOURS_PATTERN = "([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]";
		Pattern pattern = Pattern.compile(TIME24HOURS_PATTERN);
		Matcher matcher = pattern.matcher(time);
		if(matcher.matches())
		{
			return time;
		}
		else
		{
			return Preference.getInstance().getScheduleTime();
		}
	}

	private class SaveChangesActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			AdminFrame.this.saveChanges();

		}

	}

	private class CloseWindowActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			AdminFrame.this.returnFocus();
			AdminFrame.this.dispose();
		}
	}

	public void moveToTop(JFrame frame) {
		// TODO Auto-generated method stub
		this.parentFrame = frame;
		frame.setAlwaysOnTop(false);
		this.setAlwaysOnTop(true);
	}

	/**
	 * give parent frame the focus.
	 */
	public void returnFocus() {
		if (this.parentFrame != null) {
			this.parentFrame.setAlwaysOnTop(true);
			this.setAlwaysOnTop(false);
		}
	}

	@Override
	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowClosing(WindowEvent e) {
		this.returnFocus();
	}

	@Override
	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	protected JLabel getLabel() {
		return this.lblVersionNumber;
	}

	public static boolean isIsrestart() {
		return isrestart;
	}

	public static void setIsrestart(boolean isrestart) {
		AdminFrame.isrestart = isrestart;
	}

	@Override
	public void valueChanged(TreeSelectionEvent e) {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getPath().getLastPathComponent();
		if (node == null) {
			return;
		}

		// display appropriate data on the right of the panel
		if (node.getUserObject() instanceof PlaylistRecord) {
			this.playlistManagerPane.setRightComponent(new PlaylistRecordView((PlaylistRecord)node.getUserObject()));
		} else {
			this.playlistManagerPane.setRightComponent(new JLabel(node.getUserObject().toString()));
		}
	}
}
